package Proj_pack;

public class Worker implements Runnable {

	@Override
	public void run() {

		while (true) {
			boolean brk = false;
			Mash aktMash = null;
			aktMash = netz2135.unstable.poll(); // poll liefert genau dann null
												// wenn unstable leer ist sonst
												// das erste element
			if (aktMash == null) {
				break; // wenn fuer den thread die queue leer war, terminiert
						// er, wenn der Algo. noch nicht fertig ist, aber die
						// queue leer war, ist noch eine anderer thread am
						// arbeiten also ist das nicht der letze und darf vorzeitig
						// terminieren.
			}
			// erstellt ein int[] als kopie representation der knoten des
			// splitters - wartet auf lock von aktMash - da wir sonst noch kein
			// lock haben gibts kein hold-and-wait
			int[] splitter = aktMash.getSplitter();

			for (Knoten aktKnoten : aktMash.getkList()) { // lock auf aktmash
															// war wieder offen,
															// aktmash kann aber
															// nur kleiner
															// geworden sein
				if (brk)
					break;

				for (Knoten preKnoten : aktKnoten.getVorganger()) { // ueber
																	// alle
																	// vorganger
																	// ohne
																	// locks
					if (brk)
						break;
					boolean neuAnders = false;
					Mash neu = null;
					Mash preMash = preKnoten.tryGetMash(); // versucht das lock
															// und die mashe von
															// vorgangerknoten
															// zu holen, wenn
															// das lock nicht
															// frei ist ist
															// mash=null
					if (preMash != null) { // wenn wir das lock auf preMash
											// nicht bekommen haben brechen wir
											// alles ab.
						try {
							neu = new Mash(preMash.getCap());// wird noch nicht
																// zu unstabel
																// gemacht.
							neu.lock.lock();
							try {
								for (Knoten knotenAusVorMash : preMash
										.getkList()) { // alle knoten aus
														// preMash in neu
														// verschieben, die
														// nicht auf spliter
														// zeigen
									if (!knotenAusVorMash
											.zeigtAufSplitter(splitter)) {
										knotenAusVorMash.changeMash(neu); // verschieben
																			// braucht
																			// locks
																			// von
																			// preMash
																			// und
																			// neu
									}
								}
								if (!neu.getkList().isEmpty())
									neuAnders = true; // mit neuAnders merken
														// wir uns, ob wir
														// knoten in neu
														// verschoben haben,
														// wobei neu noch
														// gelockt sein muss
							} finally {
								neu.lock.unlock(); // neu freigeben
							}
						} finally {
							preMash.lock.unlock(); // wenn wir auf preMash
													// arbeiten wollten sind wir
													// jetzt fertig
						}
						if (neuAnders) { // wird nur ausgefuert wenn wir preMash
											// geteilt haben
							netz2135.maschen.add(neu);
							netz2135.unstable.add(neu); // die beiden
														// bearbeiteten mashen
														// als spliter in die
														// unstable-queue
							netz2135.unstable.add(preMash); // irgendwie ist
															// alles schneller
															// wenn wir addFirst
															// anstelle von
															// addLast benutzen
															// (???)
						}

					} else {
						brk = true;
						netz2135.unstable.add(aktMash);
						break;
					}
				}
			}
		}
		// System.err.println(Thread.currentThread() + " zuende");
		netz2135.resultWait.countDown();
	}
}
